{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from llvmlite import ir"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Build a simple function with a for loop that sum the first N integer, where N is the argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "m = ir.Module()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "i32 (i32)\n"
     ]
    }
   ],
   "source": [
    "fnty = ir.FunctionType(ir.IntType(32), [ir.IntType(32)])\n",
    "print(fnty)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "declare i32 @\"count_number\"(i32 %\"N\") \n",
      "\n"
     ]
    }
   ],
   "source": [
    "fn = ir.Function(m, fnty, \"count_number\")\n",
    "fn.args[0].name= 'N'\n",
    "print(fn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "builder = ir.IRBuilder(fn.append_basic_block('entry'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Initialize variable `ct` and `out` with `0`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "define i32 @\"count_number\"(i32 %\"N\") \n",
      "{\n",
      "entry:\n",
      "  %\"out\" = alloca i32\n",
      "  %\"ct\" = alloca i32\n",
      "  store i32 0, i32* %\"out\"\n",
      "  store i32 0, i32* %\"ct\"\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "out = builder.alloca(ir.IntType(32), name='out')\n",
    "ct = builder.alloca(ir.IntType(32), name='ct')\n",
    "builder.store(out.type.pointee(0), out)\n",
    "builder.store(ct.type.pointee(0), ct)\n",
    "print(fn)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Populate loop header"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "define i32 @\"count_number\"(i32 %\"N\") \n",
      "{\n",
      "entry:\n",
      "  %\"out\" = alloca i32\n",
      "  %\"ct\" = alloca i32\n",
      "  store i32 0, i32* %\"out\"\n",
      "  store i32 0, i32* %\"ct\"\n",
      "  br label %\"loop.header\"\n",
      "loop.header:\n",
      "  %\".6\" = load i32, i32* %\"ct\"\n",
      "  %\".7\" = icmp slt i32 %\".6\", %\"N\"\n",
      "  br i1 %\".7\", label %\"loop.body\", label %\"loop.end\"\n",
      "loop.body:\n",
      "loop.end:\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "loophead = fn.append_basic_block('loop.header')\n",
    "loopbody = fn.append_basic_block('loop.body')\n",
    "loopend = fn.append_basic_block('loop.end')\n",
    "\n",
    "builder.branch(loophead)\n",
    "builder.position_at_end(loophead)\n",
    "\n",
    "# loop if ct < arg0\n",
    "arg0 = fn.args[0]\n",
    "pred = builder.icmp_signed('<', builder.load(ct), arg0)\n",
    "builder.cbranch(pred, loopbody, loopend)\n",
    "\n",
    "print(fn)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Populate loop body"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "define i32 @\"count_number\"(i32 %\"N\") \n",
      "{\n",
      "entry:\n",
      "  %\"out\" = alloca i32\n",
      "  %\"ct\" = alloca i32\n",
      "  store i32 0, i32* %\"out\"\n",
      "  store i32 0, i32* %\"ct\"\n",
      "  br label %\"loop.header\"\n",
      "loop.header:\n",
      "  %\".6\" = load i32, i32* %\"ct\"\n",
      "  %\".7\" = icmp slt i32 %\".6\", %\"N\"\n",
      "  br i1 %\".7\", label %\"loop.body\", label %\"loop.end\"\n",
      "loop.body:\n",
      "  %\".9\" = load i32, i32* %\"out\"\n",
      "  %\".10\" = load i32, i32* %\"ct\"\n",
      "  %\".11\" = add i32 %\".9\", %\".10\"\n",
      "  store i32 %\".11\", i32* %\"out\"\n",
      "  %\".13\" = load i32, i32* %\"ct\"\n",
      "  %\".14\" = add i32 %\".13\", 1\n",
      "  store i32 %\".14\", i32* %\"ct\"\n",
      "  br label %\"loop.header\"\n",
      "loop.end:\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "builder.position_at_end(loopbody)\n",
    "\n",
    "# out += ct\n",
    "builder.store(builder.add(builder.load(out), builder.load(ct)), out)\n",
    "# ct += 1\n",
    "builder.store(builder.add(builder.load(ct), ct.type.pointee(1)), ct)\n",
    "# jump to loophead\n",
    "builder.branch(loophead)\n",
    "\n",
    "print(fn)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Populate loop end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "define i32 @\"count_number\"(i32 %\"N\") \n",
      "{\n",
      "entry:\n",
      "  %\"out\" = alloca i32\n",
      "  %\"ct\" = alloca i32\n",
      "  store i32 0, i32* %\"out\"\n",
      "  store i32 0, i32* %\"ct\"\n",
      "  br label %\"loop.header\"\n",
      "loop.header:\n",
      "  %\".6\" = load i32, i32* %\"ct\"\n",
      "  %\".7\" = icmp slt i32 %\".6\", %\"N\"\n",
      "  br i1 %\".7\", label %\"loop.body\", label %\"loop.end\"\n",
      "loop.body:\n",
      "  %\".9\" = load i32, i32* %\"out\"\n",
      "  %\".10\" = load i32, i32* %\"ct\"\n",
      "  %\".11\" = add i32 %\".9\", %\".10\"\n",
      "  store i32 %\".11\", i32* %\"out\"\n",
      "  %\".13\" = load i32, i32* %\"ct\"\n",
      "  %\".14\" = add i32 %\".13\", 1\n",
      "  store i32 %\".14\", i32* %\"ct\"\n",
      "  br label %\"loop.header\"\n",
      "loop.end:\n",
      "  %\".17\" = load i32, i32* %\"out\"\n",
      "  ret i32 %\".17\"\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "builder.position_at_end(loopend)\n",
    "\n",
    "builder.ret(builder.load(out))\n",
    "\n",
    "print(fn)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Visualize CFG"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg height=\"417pt\" viewBox=\"0.00 0.00 366.49 417.00\" width=\"366pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 413)\">\n",
       "<title>CFG for 'count_number' function</title>\n",
       "<polygon fill=\"white\" points=\"-4,4 -4,-413 362.492,-413 362.492,4 -4,4\" stroke=\"none\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"179.246\" y=\"-6.8\">CFG for 'count_number' function</text>\n",
       "<!-- Node0x105211c20 -->\n",
       "<g class=\"node\" id=\"node1\"><title>Node0x105211c20</title>\n",
       "<polygon fill=\"none\" points=\"80.7236,-316.5 80.7236,-408.5 224.269,-408.5 224.269,-316.5 80.7236,-316.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"88.7236\" y=\"-393.3\">entry:</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"88.7236\" y=\"-379.3\"> %out = alloca i32</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"88.7236\" y=\"-365.3\"> %ct = alloca i32</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"88.7236\" y=\"-351.3\"> store i32 0, i32* %out</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"88.7236\" y=\"-337.3\"> store i32 0, i32* %ct</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"88.7236\" y=\"-323.3\"> br label %loop.header</text>\n",
       "</g>\n",
       "<!-- Node0x105211c90 -->\n",
       "<g class=\"node\" id=\"node2\"><title>Node0x105211c90</title>\n",
       "<polygon fill=\"none\" points=\"15.478,-193.5 15.478,-279.5 289.514,-279.5 289.514,-193.5 15.478,-193.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"23.478\" y=\"-264.3\">loop.header: </text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"23.478\" y=\"-250.3\"> %.6 = load i32, i32* %ct</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"23.478\" y=\"-236.3\"> %.7 = icmp slt i32 %.6, %N</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"23.478\" y=\"-222.3\"> br i1 %.7, label %loop.body, label %loop.end</text>\n",
       "<polyline fill=\"none\" points=\"15.478,-215.5 289.514,-215.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"83.7539\" y=\"-200.3\">T</text>\n",
       "<polyline fill=\"none\" points=\"152.03,-193.5 152.03,-215.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"220.423\" y=\"-200.3\">F</text>\n",
       "</g>\n",
       "<!-- Node0x105211c20&#45;&gt;Node0x105211c90 -->\n",
       "<g class=\"edge\" id=\"edge1\"><title>Node0x105211c20-&gt;Node0x105211c90</title>\n",
       "<path d=\"M152.496,-316.382C152.496,-307.822 152.496,-298.796 152.496,-290.029\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"155.996,-289.9 152.496,-279.9 148.996,-289.9 155.996,-289.9\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- Node0x105211f40 -->\n",
       "<g class=\"node\" id=\"node3\"><title>Node0x105211f40</title>\n",
       "<polygon fill=\"none\" points=\"0,-22.5 0,-156.5 166.992,-156.5 166.992,-22.5 0,-22.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-141.3\">loop.body: </text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-127.3\"> %.9 = load i32, i32* %out</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-113.3\"> %.10 = load i32, i32* %ct</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-99.3\"> %.11 = add i32 %.9, %.10</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-85.3\"> store i32 %.11, i32* %out</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-71.3\"> %.13 = load i32, i32* %ct</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-57.3\"> %.14 = add i32 %.13, 1</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-43.3\"> store i32 %.14, i32* %ct</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-29.3\"> br label %loop.header</text>\n",
       "</g>\n",
       "<!-- Node0x105211c90&#45;&gt;Node0x105211f40 -->\n",
       "<g class=\"edge\" id=\"edge2\"><title>Node0x105211c90:s0-&gt;Node0x105211f40</title>\n",
       "<path d=\"M83.4961,-193C83.4961,-184.558 83.4961,-175.726 83.4961,-166.937\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"86.9962,-166.666 83.4961,-156.666 79.9962,-166.666 86.9962,-166.666\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- Node0x105212170 -->\n",
       "<g class=\"node\" id=\"node4\"><title>Node0x105212170</title>\n",
       "<polygon fill=\"none\" points=\"184.5,-64.5 184.5,-114.5 358.492,-114.5 358.492,-64.5 184.5,-64.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"192.5\" y=\"-99.3\">loop.end: </text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"192.5\" y=\"-85.3\"> %.17 = load i32, i32* %out</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"192.5\" y=\"-71.3\"> ret i32 %.17</text>\n",
       "</g>\n",
       "<!-- Node0x105211c90&#45;&gt;Node0x105212170 -->\n",
       "<g class=\"edge\" id=\"edge3\"><title>Node0x105211c90:s1-&gt;Node0x105212170</title>\n",
       "<path d=\"M289.496,-204.5C322.463,-204.5 305.619,-157.411 289.374,-123.761\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"292.441,-122.067 284.85,-114.676 286.175,-125.188 292.441,-122.067\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- Node0x105211f40&#45;&gt;Node0x105211c90 -->\n",
       "<g class=\"edge\" id=\"edge4\"><title>Node0x105211f40-&gt;Node0x105211c90</title>\n",
       "<path d=\"M114.961,-156.621C119.348,-165.841 123.801,-175.2 128.034,-184.094\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"124.896,-185.644 132.353,-193.17 131.216,-182.636 124.896,-185.644\" stroke=\"black\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>"
      ],
      "text/plain": [
       "<IPython.core.display.SVG object>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from llvmlite import binding as llvm\n",
    "\n",
    "dot = llvm.get_function_cfg(fn)\n",
    "llvm.view_dot_graph(dot)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Optimize the function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "; ModuleID = '<string>'\n",
      "target triple = \"unknown-unknown-unknown\"\n",
      "\n",
      "; Function Attrs: norecurse nounwind readnone\n",
      "define i32 @count_number(i32 %N) #0 {\n",
      "entry:\n",
      "  %.71 = icmp sgt i32 %N, 0\n",
      "  br i1 %.71, label %loop.body.preheader, label %loop.end\n",
      "\n",
      "loop.body.preheader:                              ; preds = %entry\n",
      "  %0 = add i32 %N, -1\n",
      "  %1 = zext i32 %0 to i33\n",
      "  %2 = add i32 %N, -2\n",
      "  %3 = zext i32 %2 to i33\n",
      "  %4 = mul i33 %1, %3\n",
      "  %5 = lshr i33 %4, 1\n",
      "  %6 = trunc i33 %5 to i32\n",
      "  %7 = add i32 %6, %N\n",
      "  %8 = add i32 %7, -1\n",
      "  br label %loop.end\n",
      "\n",
      "loop.end:                                         ; preds = %loop.body.preheader, %entry\n",
      "  %out.0.lcssa = phi i32 [ 0, %entry ], [ %8, %loop.body.preheader ]\n",
      "  ret i32 %out.0.lcssa\n",
      "}\n",
      "\n",
      "attributes #0 = { norecurse nounwind readnone }\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# materialize a LLVM module\n",
    "mod = llvm.parse_assembly(str(m))\n",
    "\n",
    "# create optimizer\n",
    "pm = llvm.create_module_pass_manager()\n",
    "pmb = llvm.create_pass_manager_builder()\n",
    "pmb.opt_level = 3  # -O3\n",
    "pmb.populate(pm)\n",
    "\n",
    "# optimize\n",
    "pm.run(mod)\n",
    "\n",
    "print(mod)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "View optimized CFG"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg height=\"389pt\" viewBox=\"0.00 0.00 401.50 389.00\" width=\"402pt\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
       "<g class=\"graph\" id=\"graph0\" transform=\"scale(1 1) rotate(0) translate(4 385)\">\n",
       "<title>CFG for 'count_number' function</title>\n",
       "<polygon fill=\"white\" points=\"-4,4 -4,-385 397.501,-385 397.501,4 -4,4\" stroke=\"none\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"196.75\" y=\"-6.8\">CFG for 'count_number' function</text>\n",
       "<!-- Node0x104ca69d0 -->\n",
       "<g class=\"node\" id=\"node1\"><title>Node0x104ca69d0</title>\n",
       "<polygon fill=\"none\" points=\"43.1694,-308.5 43.1694,-380.5 382.332,-380.5 382.332,-308.5 43.1694,-308.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"51.1694\" y=\"-365.3\">entry:</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"51.1694\" y=\"-351.3\"> %.71 = icmp sgt i32 %N, 0</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"51.1694\" y=\"-337.3\"> br i1 %.71, label %loop.body.preheader, label %loop.end</text>\n",
       "<polyline fill=\"none\" points=\"43.1694,-330.5 382.332,-330.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"127.945\" y=\"-315.3\">T</text>\n",
       "<polyline fill=\"none\" points=\"212.721,-308.5 212.721,-330.5 \" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"middle\" x=\"297.114\" y=\"-315.3\">F</text>\n",
       "</g>\n",
       "<!-- Node0x104c57210 -->\n",
       "<g class=\"node\" id=\"node2\"><title>Node0x104c57210</title>\n",
       "<polygon fill=\"none\" points=\"62.1733,-109.5 62.1733,-271.5 223.328,-271.5 223.328,-109.5 62.1733,-109.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-256.3\">loop.body.preheader: </text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-242.3\"> %0 = add i32 %N, -1</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-228.3\"> %1 = zext i32 %0 to i33</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-214.3\"> %2 = add i32 %N, -2</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-200.3\"> %3 = zext i32 %2 to i33</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-186.3\"> %4 = mul i33 %1, %3</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-172.3\"> %5 = lshr i33 %4, 1</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-158.3\"> %6 = trunc i33 %5 to i32</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-144.3\"> %7 = add i32 %6, %N</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-130.3\"> %8 = add i32 %7, -1</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"70.1733\" y=\"-116.3\"> br label %loop.end</text>\n",
       "</g>\n",
       "<!-- Node0x104ca69d0&#45;&gt;Node0x104c57210 -->\n",
       "<g class=\"edge\" id=\"edge1\"><title>Node0x104ca69d0:s0-&gt;Node0x104c57210</title>\n",
       "<path d=\"M127.75,-308C127.75,-299.406 128.157,-290.485 128.836,-281.577\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"132.329,-281.81 129.711,-271.543 125.355,-281.201 132.329,-281.81\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- Node0x1054039c0 -->\n",
       "<g class=\"node\" id=\"node3\"><title>Node0x1054039c0</title>\n",
       "<polygon fill=\"none\" points=\"0,-22.5 0,-72.5 393.501,-72.5 393.501,-22.5 0,-22.5\" stroke=\"black\"/>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-57.3\">loop.end: </text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-43.3\"> %out.0.lcssa = phi i32 [ 0, %entry ], [ %8, %loop.body.preheader ]</text>\n",
       "<text font-family=\"Times,serif\" font-size=\"14.00\" text-anchor=\"start\" x=\"8\" y=\"-29.3\"> ret i32 %out.0.lcssa</text>\n",
       "</g>\n",
       "<!-- Node0x104ca69d0&#45;&gt;Node0x1054039c0 -->\n",
       "<g class=\"edge\" id=\"edge2\"><title>Node0x104ca69d0:s1-&gt;Node0x1054039c0</title>\n",
       "<path d=\"M296.75,-308C296.75,-221.593 247.878,-129.175 218.466,-81.3789\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"221.311,-79.328 213.04,-72.7073 215.377,-83.0411 221.311,-79.328\" stroke=\"black\"/>\n",
       "</g>\n",
       "<!-- Node0x104c57210&#45;&gt;Node0x1054039c0 -->\n",
       "<g class=\"edge\" id=\"edge3\"><title>Node0x104c57210-&gt;Node0x1054039c0</title>\n",
       "<path d=\"M173.536,-109.115C177.14,-99.7059 180.651,-90.5364 183.808,-82.295\" fill=\"none\" stroke=\"black\"/>\n",
       "<polygon fill=\"black\" points=\"187.156,-83.3392 187.464,-72.7488 180.619,-80.8356 187.156,-83.3392\" stroke=\"black\"/>\n",
       "</g>\n",
       "</g>\n",
       "</svg>"
      ],
      "text/plain": [
       "<IPython.core.display.SVG object>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dot = llvm.get_function_cfg(mod.get_function(fn.name))\n",
    "llvm.view_dot_graph(dot)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice LLVM has optimized the looping away."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
